﻿using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Text;


namespace MiniCap.Transport
{
    public class RabbitMqTransport : IDisposable
    {
        private readonly string _hostName;
        private readonly string _userName;
        private readonly string _password;
        private readonly string _exchangeName;
        private readonly string _virtualHost;
        private IConnection _connection;
        private IModel _channel;


        public RabbitMqTransport(string hostName, string userName, string password,string virtualHost, string exchangeName = "minicap.exchange")
        {
            _hostName = hostName;
            _userName = userName;
            _password = password;
            _virtualHost = virtualHost;
            _exchangeName = exchangeName;
            Initialize();
        }


        private void Initialize()
        {
            var factory = new ConnectionFactory()
            {
                HostName = _hostName,
                UserName = _userName,
                Password = _password,
                VirtualHost = _virtualHost // 指定 vhost
            };


            _connection = factory.CreateConnection();
            _channel = _connection.CreateModel();


            _channel.ExchangeDeclare(exchange: _exchangeName, type: ExchangeType.Topic, durable: true);
        }


        public Task PublishAsync(string topic, string message)
        {
            var body = Encoding.UTF8.GetBytes(message);
            _channel.BasicPublish(exchange: _exchangeName,
            routingKey: topic,
            basicProperties: null,
            body: body);


            return Task.CompletedTask;
        }


        public void Subscribe(string topic, Func<string, Task> handler)
        {
            var queueName = _channel.QueueDeclare().QueueName;
            _channel.QueueBind(queue: queueName, exchange: _exchangeName, routingKey: topic);


            var consumer = new EventingBasicConsumer(_channel);
            consumer.Received += async (model, ea) =>
            {
                var body = ea.Body.ToArray();
                var message = Encoding.UTF8.GetString(body);
                await handler(message);
            };


            _channel.BasicConsume(queue: queueName, autoAck: true, consumer: consumer);
        }


        public void Dispose()
        {
            _channel?.Dispose();
            _connection?.Dispose();
        }
    }
}